package com.lagou.client;

import com.lagou.service.ServiceDiscovery;
import com.lagou.service.ServiceRegistry;
import com.lagou.service.impl.ZkServiceDiscovery;
import com.lagou.util.RpcDecoder;
import com.lagou.util.RpcEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class RpcConsumer {

    //创建线程池对象
    private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

//    private static UserClientHandler userClientHandler;
    private static ClientHandler clientHandler;
    public static boolean clientOk = false;
    //1.创建一个代理对象 providerName：UserService#sayHello are you ok?
    public static Object createProxy(final Class<?> serviceClass){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{serviceClass}, (proxy, method, args) -> {
            System.out.println("客户端invoke方法执行..hello");
            if(null==clientHandler){
                initClient();
            }
            RpcRequest rpcRequest = new RpcRequest();
            rpcRequest.setRequestId(UUID.randomUUID().toString());
            rpcRequest.setInterfaceName(method.getDeclaringClass().getName());
            rpcRequest.setMethodName(method.getName());
            rpcRequest.setParamTypes(method.getParameterTypes());
            rpcRequest.setPatams(args);
            clientHandler.setRpcRequest(rpcRequest);
            return executor.submit(clientHandler).get();
        });


    }



    //2.初始化netty客户端
    public static  void initClient() throws InterruptedException {
        clientHandler= new ClientHandler();
        NioEventLoopGroup executors = new NioEventLoopGroup();
        try{
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(executors)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast(new RpcEncoder(RpcRequest.class));
                            pipeline.addLast(new RpcDecoder(RpcResponse.class));
                            pipeline.addLast(clientHandler);
                        }
                    });
            System.out.println("客户端启动完毕");
//            clientOk=true;
//            bootstrap.connect("127.0.0.1", 8990).sync();
            // 服务发现，获取服务端地址
            ZkServiceDiscovery serviceDiscovery = new ZkServiceDiscovery();
            serviceDiscovery.init();
            String serviceAddress = null;
            if (serviceDiscovery != null){
                serviceAddress = serviceDiscovery.discover("127.0.0.1:8991");
            }
            if (serviceAddress == null){
                throw new Exception("serviceDiscovery异常");
            }

            // 连接服务端
            String[] address = serviceAddress.split(":");
            String host = address[0];

            //负载均衡策略:
            int port = Integer.parseInt(address[1]);
            System.out.println("zk get ip:"+host+"---port:"+port);
//            ChannelFuture future = bootstrap.connect(host, port).sync();
//            future.channel().closeFuture().sync();
                        clientOk=true;
            bootstrap.connect(host, port).sync();

        }catch (Exception e){
            e.printStackTrace();
        }
    }


}
